package com.zz.framework.core.ext

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlin.coroutines.cancellation.CancellationException

/**
 * Copyright © 2024 zhun All rights reserved.
 * Created by Zha0Zhun on 2024/7/28 12:59.
 * @author: Zha0Zhun 1820022519@qq.com
 * @version: V1.0
 */
/**
 * Check if the channel is not closed and try to emit a value, catching [CancellationException] if the corresponding
 * has been cancelled. This extension is used in call callbackFlow.
 */
fun <E> SendChannel<E>.safeSend(value: E): Boolean {
    if (isClosedForSend) return false
    return try {
        trySend(value).isSuccess
    } catch (e: CancellationException) {
        false
    }
}

/**
 * Terminal flow operator that collects the given flow with a provided [action] and catch [CancellationException]
 */
suspend inline fun <T> Flow<T>.safeCollect(crossinline action: suspend (value: T) -> Unit): Unit =
    collect { value ->
        try {
            action(value)
        } catch (e: CancellationException) {
            e.printStackTrace()
        }
    }

/**
 * Terminal flow operator that [launches][launch] the [collection][collect] of the given flow in the [scope] and catch
 * [CancellationException]
 * It is a shorthand for `scope.launch { flow.safeCollect {} }`.
 */
fun <T> Flow<T>.safeLaunchIn(scope: CoroutineScope) = scope.launch {
    this@safeLaunchIn.safeCollect { /* Do nothing */ }
}